using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

namespace SqlRunner.uiStatus
{
    /// <summary>
    /// Stores user interface components that have in common a boolean property
    /// A binary flag is stored with the collection to indicate
    /// when the boolean property is set.
    /// </summary>
    public class GroupControls<T>
    {

        #region Private Instances

        private readonly string Property;
        private readonly int Flag;
        private readonly List<Component> Controls;

        #endregion
        #region Public Methods

        /// <summary>
        /// Creates a collection of controls that contain a boolean property and want
        /// to be updated at the same time when a condition is met.
        /// </summary>
        /// <param name="property">Common property for the stored components</param>
        /// <param name="flag">Binary value to indicate when property is set</param>
        public GroupControls(string property, T flag)
        {
            if (!flag.GetType().IsEnum)
                throw new ArgumentException("The flag parameter must be an enumeration");
            Property = property;
            Flag = (int) (object) flag;
            Controls = new List<Component>();
        }

        /// <summary>
        /// Adds a new control to the collection
        /// </summary>
        /// <param name="control">New control</param>
        public void AddControl(Component control)
        {
            Type t = control.GetType();
            IEnumerator iterator = t.GetProperties().GetEnumerator();
            bool isFound = false;
			
            while ( !isFound & iterator.MoveNext())
            {
                PropertyInfo property = (PropertyInfo) iterator.Current;
                if ( property.Name.Equals(Property) )
                {
                    Controls.Add(control);
                    isFound = true;
                }
            }
        }

        /// <summary>
        /// A binary AND operation is carried out between the passed value and the binary value
        /// used when the collection was created. The property of all the controls are set if the
        /// returned value is the same that the passed value, if not, then the property is disabled.
        /// </summary>
        /// <param name="status">Binary value</param>
        public void UpdateProperty(T status)
        {
            var statusToInt = (int) (object) status;
            bool result = (Flag & statusToInt) == statusToInt? true : false; 
            foreach (Component control in Controls)
            {
                Type t = control.GetType();
                PropertyInfo property = t.GetProperty(Property);
                property.SetValue(control, result, null);
            }
        }
        #endregion

    }
}